﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
using System.Threading;

namespace A2DFramework.CacheService.CacheProvider.LocalCache
{
    public abstract class BaseCacheContainer
    {
        protected int capacity;
        protected ConcurrentDictionary<object, BaseCacheItem> dic;

        Timer timer;
        public BaseCacheContainer()
        {
            timer = new Timer(new TimerCallback(ProcessExpirateTime), null, 1000, 1000);
        }

        public abstract object Get(object key);

        public virtual void Set(object key, object value)
        {
            Set(key, value, TimeSpan.FromSeconds(60));//这个value要传进来，不能硬编码
        }
        public virtual void Set(object key, object value, CacheExpireType expireType, double increment)
        {
            if (expireType == CacheExpireType.Absolutely)
                Set(key, value, DateTime.Now.AddSeconds(increment));
            else if (expireType == CacheExpireType.Forever)
                Set(key, value);
            else if (expireType == CacheExpireType.Slide)
                Set(key, value);
        }
        public virtual void Set(object key, object value, DateTime absolutelyExpireTime)
        {
            Set(key, value, CacheExpireType.Absolutely, absolutelyExpireTime, TimeSpan.MinValue);
        }
        public virtual void Set(object key, object value, TimeSpan slideIncrement)
        {
            Set(key, value, CacheExpireType.Slide, DateTime.MaxValue, slideIncrement);
        }
        public abstract void Set(object key, object value, CacheExpireType expireType, DateTime absolutelyExpireTime, TimeSpan slideIncrement);

        public abstract void Remove(object key);
        private void ProcessExpirateTime(object state)
        {
        startcheck:
            foreach (var key in this.dic.Keys)
            {
                BaseCacheItem current;
                if (!this.dic.TryGetValue(key, out current))
                    continue;

                if (current.ExpireTime != DateTime.MinValue &&
                    current.ExpireTime != DateTime.MaxValue)
                {
                    if (current.ExpireTime <= DateTime.Now)
                    {
                        Remove(current.Key);
                        goto startcheck;
                    }
                }
                if (current.ExpireType == CacheExpireType.Absolutely)
                {
                }
                else if (current.ExpireType == CacheExpireType.Forever)
                {
                    current.ExpireTime = DateTime.MaxValue;
                }
                else if (current.ExpireType == CacheExpireType.Slide)
                {
                    if (current.ExpireTime == DateTime.MinValue || current.ExpireTime == DateTime.MaxValue)
                        current.ExpireTime = DateTime.Now.AddSeconds(current.SlideIncrement.TotalSeconds);
                }
            }
        }
    }
}